#include "ActionExt.h"
#include "CCATFileCache.h"
#include "CC2DFileCache.h"
#include "Misc.h"

//
// SoundPlay
//
VSoundPlay* VSoundPlay::action(const char* path, float volume/* =1.0f */) 
{
	VSoundPlay* pRet = new VSoundPlay();

	if (pRet) 
	{
		pRet->initWithFile(path, volume);
		pRet->autorelease();
	}

	return pRet;
}

void VSoundPlay::initWithFile(const char* path, float volume/* =1.0f */)
{
	m_strSound = path;
	m_volume = volume;
}

void VSoundPlay::startWithTarget(CCNode *pTarget) 
{
	CCActionInstant::startWithTarget(pTarget);
	CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(m_volume);
	CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(m_strSound.c_str());
}

CCFiniteTimeAction* VSoundPlay::reverse() 
{
	CCAssert(0,"VSoundPlay cann't reverse !");
	return NULL;
}

CCObject* VSoundPlay::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VSoundPlay* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VSoundPlay*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VSoundPlay();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCActionInstant::copyWithZone(pZone);

	pCopy->initWithFile(m_strSound.c_str());

	CC_SAFE_DELETE(pNewZone);
	return pCopy;
}

//
// Delete Node
//

VDeleteNode* VDeleteNode::action() 
{
	VDeleteNode* pRet = new VDeleteNode();

	if (pRet) 
	{
		pRet->autorelease();
	}

	return pRet;
}

void VDeleteNode::startWithTarget(CCNode *pTarget) 
{
	CCActionInstant::startWithTarget(pTarget);
	if (pTarget)
	{
		pTarget->removeFromParentAndCleanup(true);
	}
}

CCFiniteTimeAction* VDeleteNode::reverse() 
{
	CCAssert(0,"VDeleteNode cann't reverse !");
	return NULL;
}

CCObject* VDeleteNode::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VDeleteNode* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VDeleteNode*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VDeleteNode();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCActionInstant::copyWithZone(pZone);

	CC_SAFE_DELETE(pNewZone);
	return pCopy;
}

//
// SetGridNull
//

VSetGridNull* VSetGridNull::action() 
{
	VSetGridNull* pRet = new VSetGridNull();

	if (pRet) 
	{
		pRet->autorelease();
	}

	return pRet;
}

void VSetGridNull::startWithTarget(CCNode *pTarget) 
{
	CCActionInstant::startWithTarget(pTarget);
	if (pTarget)
	{
		pTarget->setGrid(NULL);
	}
}

CCFiniteTimeAction* VSetGridNull::reverse() 
{
	CCAssert(0,"VDeleteNode cann't reverse !");
	return NULL;
}

CCObject* VSetGridNull::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VSetGridNull* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VSetGridNull*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VSetGridNull();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCActionInstant::copyWithZone(pZone);

	CC_SAFE_DELETE(pNewZone);
	return pCopy;
}
//
// VNodeRunAction Node
//

VNodeRunAction* VNodeRunAction::actionWithNodeName(const char* nodeName, const char* actName, const char* ccatFile, FindFromType findType) 
{
	VNodeRunAction* pRet = new VNodeRunAction();

	if (pRet && pRet->initWithNodeName(nodeName, actName, ccatFile, findType)) 
	{
		pRet->autorelease();
	}
	else
	{
		CC_SAFE_DELETE(pRet);
	}

	return pRet;
}

bool VNodeRunAction::initWithNodeName(const char* nodeName, const char* actName, const char* ccatFile, FindFromType findType)
{	
	m_nodeName = nodeName;
	m_actionName = actName;
	m_ccatFile = ccatFile;
	m_findType = findType;

	return true;
}

void VNodeRunAction::startWithTarget(CCNode *pTarget) 
{
	CCActionInstant::startWithTarget(pTarget);
	if (pTarget)
	{
		switch(m_findType)
		{
		case FindFrom_Sefl:
			{
				CCNode* pNode = NULL;
				if (m_nodeName.empty())
				{
					pNode = pTarget;
				}
				else
				{
					pNode = Misc::getChildByName(pTarget, m_nodeName.c_str());
				}
				if (pNode)
				{
					CCAction* pAction = CCATFileCache::sharedCCATFileCache()->findAction(m_actionName.c_str(), m_ccatFile.c_str());
					if (pAction)
					{
						pNode->runAction(pAction);
					}
					else
					{
						CCLOG("VNodeRunAction::startWithTarget FindFrom_Self action=%s null, actionFile=%s null.", m_actionName.c_str(), m_ccatFile.c_str());
					}
				}
				else
				{
					CCLOG("VNodeRunAction::startWithTarget FindFrom_Self %s null.", m_nodeName.c_str());
				}
			}
			break;
		case FindFrom_Parent:
			{
				if (pTarget->getParent() == NULL)
				{
					CCLOG("VNodeRunAction::startWithTarget FindFrom_Parent getParent() %s null.");
				}

				CCNode* pNode = NULL;
				if (m_nodeName.empty())
				{
					pNode = pTarget->getParent();
				}
				else
				{
					pNode = Misc::getChildByName(pTarget->getParent(), m_nodeName.c_str());
				}

				if (pNode)
				{
					CCAction* pAction = CCATFileCache::sharedCCATFileCache()->findAction(m_actionName.c_str(), m_ccatFile.c_str());
					if (pAction)
					{
						pNode->runAction(pAction);
					}
					else
					{
						CCLOG("VNodeRunAction::startWithTarget FindFrom_Self action=%s null, actionFile=%s null.", m_actionName.c_str(), m_ccatFile.c_str());
					}
				}
				else
				{
					CCLOG("VNodeRunAction::startWithTarget FindFrom_Parent %s null.", m_nodeName.c_str());
				}
			}
			break;
		case FindFrom_Global:
			{
				CCNode* pGlobal = CCDirector::sharedDirector()->getRunningScene();
				if (pGlobal == NULL)
				{
					CCLOG("VNodeRunAction::startWithTarget FindFrom_Parent getRunningScene() %s null.");
				}

				CCNode* pNode = NULL;

				if (m_nodeName.empty())
				{
					pNode = pGlobal;
				}
				else
				{
					pNode = Misc::getChildByName(pGlobal, m_nodeName.c_str());
				}
				if (pNode)
				{
					CCAction* pAction = CCATFileCache::sharedCCATFileCache()->findAction(m_actionName.c_str(), m_ccatFile.c_str());
					if (pAction)
					{
						pNode->runAction(pAction);
					}
					else
					{
						CCLOG("VNodeRunAction::startWithTarget FindFrom_Self action=%s null, actionFile=%s null.", m_actionName.c_str(), m_ccatFile.c_str());
					}
				}
				else
				{
					CCLOG("VNodeRunAction::startWithTarget FindFrom_Parent %s null.", m_nodeName.c_str());
				}
			}
			break;
		}
	}
}

CCFiniteTimeAction* VNodeRunAction::reverse() 
{
	CCAssert(0,"VDeleteNode cann't reverse !");
	return NULL;
}

CCObject* VNodeRunAction::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VNodeRunAction* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VNodeRunAction*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VNodeRunAction();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCActionInstant::copyWithZone(pZone);

	pCopy->initWithNodeName(m_nodeName.c_str(), m_actionName.c_str(), m_ccatFile.c_str(), m_findType);
	CC_SAFE_DELETE(pNewZone);

	return pCopy;
}

// VCC2DLoad


VCC2DLoad* VCC2DLoad::actionWithFile(const char* cc2dFile, const char* parentNodeName, FindFromType findType) 
{
	VCC2DLoad* pRet = new VCC2DLoad();

	if (pRet && pRet->initWithFile(cc2dFile, parentNodeName, findType)) 
	{
		pRet->autorelease();
	}

	return pRet;
}

bool VCC2DLoad::initWithFile(const char* cc2dFile, const char* parentNodeName, FindFromType findType)
{
	m_parentNodeName = parentNodeName;
	m_cc2dFile = cc2dFile;
	m_findType = findType;
	return true;
}

void VCC2DLoad::startWithTarget(CCNode *pTarget) 
{
	CCActionInstant::startWithTarget(pTarget);
	if (pTarget)
	{
		switch(m_findType)
		{
		case FindFrom_Sefl:
			{
				CCNode* pNode = NULL;
				if (m_parentNodeName.empty())
				{
					pNode = pTarget;
				}
				else
				{
					pNode = Misc::getChildByName(pTarget, m_parentNodeName.c_str());
				}

				if (pNode)
				{
					CC2DNode* pNodeData = CC2DFileCache::sharedCC2DFileCache()->addCC2DNode(m_cc2dFile.c_str());
					if (pNodeData)
					{
						pNodeData->createCCNode(pNode);
					}
					else
					{
						CCLOG("VCC2DLoad::startWithTarget FindFrom_Self cc2dFile=%s null.", m_cc2dFile.c_str());
					}
				}
				else
				{
					CCLOG("VCC2DLoad::startWithTarget FindFrom_Self %s null.", m_parentNodeName.c_str());
				}
			}
			break;
		case FindFrom_Parent:
			{
				if (pTarget->getParent() == NULL)
				{
					CCLOG("VCC2DLoad::startWithTarget FindFrom_Parent getParent() %s null.");
				}

				CCNode* pNode = NULL;
				if (m_parentNodeName.empty())
				{
					pNode = pTarget->getParent();
				}
				else
				{
					pNode = Misc::getChildByName(pTarget->getParent(),m_parentNodeName.c_str());
				}

				if (pNode)
				{
					CC2DNode* pNodeData = CC2DFileCache::sharedCC2DFileCache()->addCC2DNode(m_cc2dFile.c_str());
					if (pNodeData)
					{
						pNodeData->createCCNode(pNode);
					}
					else
					{
						CCLOG("VCC2DLoad::startWithTarget FindFrom_Self cc2dFile=%s null.", m_cc2dFile.c_str());
					}
				}
				else
				{
					CCLOG("VCC2DLoad::startWithTarget FindFrom_Self %s null.", m_parentNodeName.c_str());
				}
			}
			break;
		case FindFrom_Global:
			{
				CCNode* pGlobal = CCDirector::sharedDirector()->getRunningScene();
				if (pGlobal == NULL)
				{
					CCLOG("VCC2DLoad::startWithTarget FindFrom_Parent getRunningScene() %s null.");
				}

				CCNode* pNode = NULL;
				if (m_parentNodeName.empty())
				{
					pNode = pGlobal;
				}
				else
				{
					pNode = Misc::getChildByName(pGlobal, m_parentNodeName.c_str());
				}

				if (pNode)
				{
					CC2DNode* pNodeData = CC2DFileCache::sharedCC2DFileCache()->addCC2DNode(m_cc2dFile.c_str());
					if (pNodeData)
					{
						pNodeData->createCCNode(pNode);
					}
					else
					{
						CCLOG("VCC2DLoad::startWithTarget FindFrom_Self cc2dFile=%s null.", m_cc2dFile.c_str());
					}
				}
				else
				{
					CCLOG("VCC2DLoad::startWithTarget FindFrom_Self %s null.", m_parentNodeName.c_str());
				}
			}
			break;
		}
	}
}

CCFiniteTimeAction* VCC2DLoad::reverse() 
{
	CCAssert(0,"VDeleteNode cann't reverse !");
	return NULL;
}

CCObject* VCC2DLoad::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VCC2DLoad* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VCC2DLoad*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VCC2DLoad();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCActionInstant::copyWithZone(pZone);

	pCopy->initWithFile(m_cc2dFile.c_str(), m_parentNodeName.c_str(), m_findType);

	CC_SAFE_DELETE(pNewZone);
	return pCopy;
}


//
// Delaytime by a random number
//
/*VRandomDelayTime* VRandomDelayTime::actionWithRange(float Min, float Max) 
{
	VRandomDelayTime* pRet = new VRandomDelayTime();

	if (pRet) 
	{
		pRet->initWithRange(Min, Max);
		float d = Min + (float)(rand()%(int)(Max-Min));
		pRet->initWithDuration(d);
		pRet->autorelease();
	}

	return pRet;
}

CCObject* VRandomDelayTime::copyWithZone(CCZone *pZone) 
{
	CCZone* pNewZone = NULL;
	VRandomDelayTime* pCopy = NULL;
	if(pZone && pZone->m_pCopyObject) 
	{
		//in case of being called at sub class
		pCopy = (VRandomDelayTime*)(pZone->m_pCopyObject);
	}
	else
	{
		pCopy = new VRandomDelayTime();
		pZone = pNewZone = new CCZone(pCopy);
	}

	CCDelayTime::copyWithZone(pZone);

	pCopy->initWithRange(m_Min, m_Max);

	CC_SAFE_DELETE(pNewZone);
	return pCopy;
}

void VRandomDelayTime::startWithTarget(CCNode *pTarget)
{
	CCDelayTime::startWithTarget(pTarget);

	float d = m_Min + (float)(rand()%(int)(m_Max-m_Min));
	m_fDuration = d;
}

void VRandomDelayTime::initWithRange(float Min, float Max)
{
	m_Min = Min;
	m_Max = Max;
}
*/